﻿<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
  
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Brun </title>
    <meta name="viewport" content="width=device-width">
    <meta name="title" content="Brun ">
    <meta name="generator" content="docfx 2.28.3.0">
    
    <link rel="shortcut icon" href="favicon.ico">
    <link rel="stylesheet" href="styles/docfx.vendor.css">
    <link rel="stylesheet" href="styles/docfx.css">
    <link rel="stylesheet" href="styles/main.css">
    <meta property="docfx:navrel" content="toc.html">
    <meta property="docfx:tocrel" content="toc.html">
    
    
    
  </head>
  <body data-spy="scroll" data-target="#affix">
    <div id="wrapper">
      <header>
        
        <nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
          <div class="container">
            <div class="navbar-header">
              <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
              </button>
              
              <a class="navbar-brand" href="index.html">
                <img id="logo" class="svg" src="logo.svg" alt="">
              </a>
            </div>
            <div class="collapse navbar-collapse" id="navbar">
              <form class="navbar-form navbar-right" role="search" id="search">
                <div class="form-group">
                  <input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
                </div>
              </form>
            </div>
          </div>
        </nav>
        
        <div class="subnav navbar navbar-default">
          <div class="container hide-when-search" id="breadcrumb">
            <ul class="breadcrumb">
              <li></li>
            </ul>
          </div>
        </div>
      </header>
      <div role="main" class="container body-content hide-when-search">
        <div class="article row grid">
          <div class="col-md-10">
            <article class="content wrap" id="_content" data-uid="">
<h1 id="brun">Brun</h1>

<h4 id="介绍">介绍</h4>
<p>netcore 轻量级后台任务，asp.net中简单易用。</p>
<p>目前仅支持内存运行，后期可能会支持持久化</p>
<ol>
<li>OnceWorker：调用第一执行一次的后台任务，可配置自定义数据。在Action里、服务里、任何其他位置调用. 继承BackRun来写自己的任务逻辑。</li>
<li>QueueWorker: 队列任务，QueueBackRun接收一个string，任何位置可传入一个string到队列，后台任务会立即执行。继承QueueBackRun来写自己的任务逻辑，请自己序列化String。</li>
<li>TimeWorker: 简单的定时任务，配置一个TimeSpan，周期执行定义的BackRun。继承BackRun来写自己的任务逻辑。</li>
</ol>
<h4 id="软件架构">软件架构</h4>
<p>基于netcore IHostedService 的后台任务组件</p>
<p>控制台和web项目都可以直接用</p>
<h4 id="安装教程">安装教程</h4>
<p>nuget搜索Brun 或自己编译</p>
<h4 id="使用说明">使用说明</h4>
<ol>
<li>创建一个继承自BackRun的类</li>
</ol>
<pre><code class="lang-csharp">//自己任务逻辑的例子，队列任务继承QueueBackRun
public class TestHttpWorker : BackRun
    {
        public async override Task Run(CancellationToken stoppingToken)
        {
            for (int i = 0; i &lt; 1; i++)
            {
                var log = GetRequiredService&lt;ILogger&lt;TestHttpWorker&gt;&gt;();
                HttpClient httpClient = new HttpClient();
                var r = await httpClient.GetAsync(&quot;http://127.0.0.1:5000/&quot;, stoppingToken);
                log.LogWarning(&quot;httpClient发起了请求,state:&quot; + r.StatusCode);

                //也能使用自带的ioc获取服务，瞬时和单例可以直接取，Scoped的需要自己创建CreateScope
                IHttpClientFactory factory= GetRequiredService&lt;IHttpClientFactory&gt;();
                var fclient= factory.CreateClient();
                var fr= await fclient.GetAsync(&quot;http://127.0.0.1:5000/&quot;, stoppingToken);
                log.LogWarning(&quot;fclient发起了请求,state:&quot; + fr.StatusCode);

                using (var scope = CreateScope())
                {
                    HttpClient iocClient = scope.ServiceProvider.GetRequiredService&lt;HttpClient&gt;();
                    var iocR = await iocClient.GetAsync(&quot;http://127.0.0.1:5000/&quot;, stoppingToken);
                    log.LogWarning(&quot;iocClient发起了请求,state:&quot; + iocR.StatusCode);
                }
            }
        }
    }
</code></pre><ol>
<li>服务配置</li>
</ol>
<pre><code class="lang-csharp">public class Program
    {
        public static string BrunKey = Guid.NewGuid().ToString();
        public static string QueueKey = Guid.NewGuid().ToString();
        public static string TimeKey = Guid.NewGuid().ToString();
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =&gt;
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =&gt;
                {
                    webBuilder.UseStartup&lt;Startup&gt;();
                })
                .ConfigureServices(services =&gt;
                {
                    //其他服务
                    services.AddHttpClient();
                    services.AddScoped&lt;ITestScopeService, TestScopeService&gt;();

                    //配置单次任务
                    WorkerBuilder.Create&lt;TestHttpWorker&gt;()
                    .SetKey(BrunKey)
                    .Build();

                    //配置队列任务
                    WorkerBuilder.CreateQueue&lt;TestQueueWorker&gt;()
                    .SetKey(QueueKey)
                    .Build();


                    //配置定时任务
                    WorkerBuilder.CreateTime&lt;ErrorTestRun&gt;()
                    .SetCycle(TimeSpan.FromSeconds(3))
                    .SetKey(TimeKey)
                    .Build();

                    //启动后台服务
                    services.AddBrunService();
                })
                ;
    }
</code></pre><ol>
<li>Action中使用例子</li>
</ol>
<pre><code class="lang-csharp">public class HomeController : Controller
    {
        private readonly ILogger&lt;HomeController&gt; _logger;
        Brun.IWorkerServer _workerServer;
        public HomeController(ILogger&lt;HomeController&gt; logger)
        {
            _logger = logger;
            _workerServer = WorkerServer.Instance;//或者构造函数中用 IWorkerServer 取
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Once()
        {
            //运行后台任务
            _workerServer.GetOnceWorker(Program.BrunKey).RunDontWait();
            return View();
        }
        public async Task&lt;IActionResult&gt; Queue(string msg)
        {
            //运行队列任务
            IQueueWorker worker = _workerServer.GetQueueWorker(Program.QueueKey);
            for (int i = 0; i &lt; 100; i++)
            {
                await worker.Enqueue(msg);
            }
            return View();
        }
        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
</code></pre></article>
          </div>
          
          <div class="hidden-sm col-md-2" role="complementary">
            <div class="sideaffix">
              <div class="contribution">
                <ul class="nav">
                </ul>
              </div>
              <nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
              <!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
              </nav>
            </div>
          </div>
        </div>
      </div>
      
      <footer>
        <div class="grad-bottom"></div>
        <div class="footer">
          <div class="container">
            <span class="pull-right">
              <a href="#top">Back to top</a>
            </span>
            <span>Copyright © 2021 xxf</span>
            
          </div>
        </div>
      </footer>
    </div>
    
    <script type="text/javascript" src="styles/docfx.vendor.js"></script>
    <script type="text/javascript" src="styles/docfx.js"></script>
    <script type="text/javascript" src="styles/main.js"></script>
  </body>
</html>
